package bachelor.view {
	import CustomEvent.CustomEvent;

	import bachelor.Globals;

	import gs.TweenLite;
	import gs.easing.Strong;

	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;

	/**
	 * @author Johannes
	 */
	public class CountryFeedback extends MovieClip 
	{
		
////////////////////////////////////////////////////////////////////////////////
/////// VARIABLES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

		// Allgemein
		private var _id : int;
		private var _loaderCounter : int = 0;
		// Layout
		private var _tintColorIndex : int;
		private var _tintColor : uint;

		// Layer
		private var _activeGrid : int = 4;
		
		// Scala
		private var _border 	: MovieClip = new MovieClip();
		private var _scala 		: MovieClip = new MovieClip();
		private var _verlauf 	: MovieClip = MovieClip(new verlaufMC()); 
		private var _slider 	: MovieClip = MovieClip(new sliderMC());
		
		// Variablen für Rechnungen
		private var _startRotation : int;
		private var _lastSliderRotationIn360 : Number;
		private var _bounceThredsholdScala : Number = 360 / 48 * _activeGrid;

		// Events
		public static const SCALA_VERLAUF_ROTATED : String = "scalaVerlaufRotated";
		public static const COUNTRY_FEEDBACK_DEINITIALIZED : String = "countryFeedbackDeinitialized";
		

////////////////////////////////////////////////////////////////////////////////
/////// CONSTRUCTOR ////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
		public function CountryFeedback(p_id : int, p_startRotation : Number, p_tintColorIndex : int) 
		{
//			trace("Feedback init ...");
			initSound();
			_id = p_id;
			_startRotation = Math.round(p_startRotation);
			_tintColorIndex = p_tintColorIndex;
			_tintColor = Globals.countryColorArray[p_tintColorIndex][1];
			init();
		}

////////////////////////////////////////////////////////////////////////////////
/////// METHODS ////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////


/////// INIT SOUND /////////////////////////////////////////////////////////////
		private function initSound() : void 
		{
			var soundInstance : fiducialAddedSound = new fiducialAddedSound();
			var trans1:SoundTransform = new SoundTransform(0.4);
			var channel1:SoundChannel = new SoundChannel();
			channel1 = soundInstance.play(0, 1, trans1);
						
		}

/////// INIT ///////////////////////////////////////////////////////////////////
		private function init() : void 
		{
//			trace("Feedback -> init() ...");
			
			/*
			 * Hintergrund
			 */
			var countryFeedbackBG : MovieClip = MovieClip(new countryFeedbackBGMC());
			countryFeedbackBG.alpha = 1;
			
			// Scala-Verlauf generieren, aber noch ausgeblendet lassen 
			/*
			 * Verlauf colorieren
			 */ 
			var verlaufColorTransform : ColorTransform = _verlauf.transform.colorTransform;
			verlaufColorTransform.color = _tintColor;
			_verlauf.transform.colorTransform = verlaufColorTransform;
			/*
			 * Gesamte Scala 
			 */ 
			_scala.addChild(countryFeedbackBG);
			_scala.addChild(_verlauf);
			_scala.addChild(_slider);
			_scala.rotation = -90;
			_scala.alpha = 0;
			addChild(_scala);


			// Unsichtbare Fläche, um die Blobs vom Fiducial abzufangen
			_border.graphics.beginFill(_tintColor, 0);
			_border.graphics.drawCircle(0, 0, 80);
			_border.graphics.endFill();
			// Grafisches Feedback: Outline
			_border.graphics.lineStyle(1.5, _tintColor, 1, true);
			_border.graphics.drawCircle(0, 0, 53);
			
			_border.alpha = 0;
			addChild(_border);
			
			showBorder();

		}
		

/////// DEINIT /////////////////////////////////////////////////////////////////
		public function deinitializeFeedback() : void
		{
			hideScala();
			hideBorder();
		}
		

////////////////////////////////////////////////////////////////////////////////
/////// BORDER /////////////////////////////////////////////////////////////////


/////// Border einblenden //////////////////////////////////////////////////////
		private function showBorder() : void 
		{
//			trace("Feedback -> showBorder() ...");
			TweenLite.to(_border, Globals.fadeTime, {alpha:1, ease:Strong.easeOut});
		}

/////// Border ausblenden //////////////////////////////////////////////////////
		private function hideBorder() : void 
		{
//			trace("Feedback -> hideBorder() ...");
			/*
			 * Das Ausblenden der Border bedeutet zwangsläufig, 
			 * dass der Fiducial entfernt wurde. 
			 * Dieses Feedback-Object deshalb removen lassen. 
			 */
			TweenLite.to(_border, Globals.fadeTime, {alpha:0, ease:Strong.easeOut, onComplete: onFeedbackDeinitialized});
		}
		
		private function onFeedbackDeinitialized() : void 
		{
//			trace("Feedback -> onFeedbackDeinitialized() ...");
			dispatchEvent(new Event(COUNTRY_FEEDBACK_DEINITIALIZED));
		}
		

		
	

////////////////////////////////////////////////////////////////////////////////
/////// SCALA //////////////////////////////////////////////////////////////////

		
/////// Scala einblenden ///////////////////////////////////////////////////////
		public function showScala() : void
		{
//			trace("Feedback -> showScala() ...");
			_loaderCounter++;
			
			if(_loaderCounter > 1) {
				_startRotation = _startRotation + _slider.rotation - 1;
//				trace("CountryFeedback -> showScala ... _startRotation: " + _startRotation);
	//			if(_startRotation < 0) {
	//				_startRotation += 360;
	//				trace("CountryFeedback -> showScala ... _startRotation war < 0, NEUER Werte: " + _startRotation);
	//			}
			}
		

			TweenLite.to(_scala, Globals.fadeTime, {alpha:1, ease:Strong.easeOut});
		}
/////// Scala ausblenden ///////////////////////////////////////////////////////
		public function hideScala() : void 
		{
//			trace("Feedback -> hideScala() ....");
			TweenLite.to(_scala, Globals.fadeTime, {alpha: 0, ease:Strong.easeOut});
		}


		
/////// Scala drehen, wenn Fiducial gedreht ////////////////////////////////////
		public function setScalaRotation(p_evt : CustomEvent) : void
		{		
//			trace("CountryFeedback -> setScalaRotation() ...");
			
			_slider.rotation = p_evt.data.rotation - _startRotation;
			
			// Flash-Rotation (-180 < rotation < 180) in vollen Kreisumfang umrechnen
			var sliderRotationIn360		: Number = (360 + _slider.rotation)  % 360;
			var verlaufRotationIn360 	: Number = (360 + _verlauf.rotation) % 360;

			var diffRotation : Number = Math.abs(sliderRotationIn360 - verlaufRotationIn360); 
			if(diffRotation > 180) 
			{ 
				// Über Null ZURÜCK gedreht
				diffRotation = 360 - Math.abs(sliderRotationIn360 - verlaufRotationIn360); 
			}

/*
 * 			trace("====================================== evt.data.rotation:   " + p_evt.data.rotation);
 *			trace("====================================== _startRotation:      " + _startRotation);
 *			trace("====================================== _slider.rotation:    " + _slider.rotation);
 *			trace("====================================== sliderRotationIn360: " + sliderRotationIn360);
 *			trace("====================================== _verlauf.rotation:   " + _verlauf.rotation);
 *			trace("====================================== diffRotation:        " + diffRotation);
 *			trace("======================================");
 */
			if( diffRotation > _bounceThredsholdScala ) 
			{

				var sliderDiff : Number = (sliderRotationIn360 - _lastSliderRotationIn360);
				if(sliderDiff < 180) 
				{ 
					// Über Null VOR gedreht
					sliderDiff += 360;
				}
				if(sliderDiff > 180)
				{
					// Über Null ZURÜCK gedreht
					sliderDiff -= 360;
				}

				var newLayerIndex : int;
				var direction : String;
				
				// LayerIndex berechnen
				if(sliderDiff < 0) 
				{
					direction = "zuruck"; 		// Heraus / rückwärts gedreht
					newLayerIndex = Math.ceil(sliderRotationIn360 / _bounceThredsholdScala); 	// aufrunden
					if(newLayerIndex > (48 / _activeGrid)) 
					{
						// Über Null ZURÜCK gedreht
						newLayerIndex = 0;
					}
				} else 
				{
					direction = "vor"; 	// Tiefer hinein / vorwärts gedreht 
					newLayerIndex = Math.floor(sliderRotationIn360 / _bounceThredsholdScala);	// abruden
				}


				_verlauf.rotation = newLayerIndex * _bounceThredsholdScala;
//				trace("CountryFeedback -> setScalaRotation() ::: newLayerIndex = " + newLayerIndex);
				dispatchEvent(new CustomEvent(SCALA_VERLAUF_ROTATED, [newLayerIndex, direction]));
				
			}
			
			/*
			 * Letzte Position des Sliders
			 */
			_lastSliderRotationIn360 = sliderRotationIn360;
		}	
		
		
////////////////////////////////////////////////////////////////////////////////
/////// getters & setter ///////////////////////////////////////////////////////
		
		public function getID() : int 
		{
			return _id;
		}

		public function getTintColorIndex() : int 
		{
//			trace("CountryFeedback -> getTintColorIndex() ::: " + _tintColorIndex);
			return _tintColorIndex;
		}

		public function setNewGrid(p_newActiveGrid : int) : void 
		{
//			trace("CountryFeedback -> setNewGrid() ...");
			// Verlauf und LayerIndex anhand des neuen Grids bestimmen
			_bounceThredsholdScala = 360 / 48 * p_newActiveGrid;
			var sliderRotationIn360	: Number 	= (360 + _slider.rotation)  % 360;
			var newLayerIndex 		: int 		= Math.floor(sliderRotationIn360 / _bounceThredsholdScala);	// abruden
			dispatchEvent(new CustomEvent(SCALA_VERLAUF_ROTATED, [newLayerIndex, "vor"]));
			_verlauf.rotation = newLayerIndex * _bounceThredsholdScala;
//			trace("CountryFeedback -> setNewGrid() ::: newLayerIndex = " + newLayerIndex);
			
			// Neues Grid dauerhaft speichern			
			_activeGrid = p_newActiveGrid;
			// Verlauf resetten
			_verlauf.rotation = 0;
		}




//		public function getStartRotation() : int 
//		{
//			return _startRotation;
//		}
//		public function setNewStartRotation(p_newStartRotation : Number) : void 
//		{
//			_startRotation = p_newStartRotation;
//		}



		
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
	}
}
